
#ifdef GL_ES
precision mediump float;
#endif

#define TMIN .1
#define TMAX 20.
#define RAYMARCH_TIME 128
#define PRECISION .001
#define AA 2

#define PI 3.1415926535

uniform vec2 u_mouse;   
uniform vec2 u_resolution;
uniform float u_time;

const vec3 translate=vec3(0.,0.,-0.);
const float radius=0.5;

//画布处理
vec2 fixUV(in vec2 c){
    return(2.*c-u_resolution.xy)/min(u_resolution.x,u_resolution.y);
}

//绘制球体
float sdfSphere(in vec3 p){
    return length(p+translate)-radius;
}

//ro源头  rd 方向
float rayMarch(in vec3 ro,in vec3 rd){
    float t=TMIN;
    for(int i=0;i<RAYMARCH_TIME ;i++){
        vec3 p=ro+t*rd;
        float d=sdfSphere(p);
        // if(d < PRECISION){break;}
        // if(t >= TMAX)  { break; }
        float isOut=step(0.,TMAX-t);
        float isAcc=step(0.,d-PRECISION);
        t+=d*isOut;
    }
    return t;
}

//计算sdf球的法向量  利用梯度即可求解
vec3 calcNormal(in vec3 p){
    float h=.0001;
    vec2 k=vec2(1.,-1.);
    return normalize(
        k.xyy*sdfSphere(p+k.xyy*h)+
        k.yyx*sdfSphere(p+k.yyx*h)+
        k.yxy*sdfSphere(p+k.yxy*h)+
        k.xxx*sdfSphere(p+k.xxx*h));
    }
    

mat3 setCamera(vec3 ta,vec3 ro,float cr){
    vec3 z = normalize(ta-ro);
    vec3 cp =vec3(sin(cr),cos(cr), .0);
    vec3 x = normalize(cross(z,cp));
    vec3 y = cross(x,z);
    return mat3(x,y,z);
}

//渲染
vec3 render(vec2 uv){
    vec3 color=vec3(0.);
    vec3 ro=vec3(2.0*cos(u_time),1.0*cos(u_time*0.5),2.0*sin(u_time));
    float theta = u_mouse.x/u_resolution.x*2.0*PI;
    ro=vec3(2.0*cos(theta),1.0,2.0*sin(theta));

    vec3 ta=vec3(0.0);
    mat3 cam = setCamera(ta,ro,0.0);
    vec3 rd=normalize(vec3(uv,1.)*cam);
    float t=rayMarch(ro,rd);
    if(t<TMAX){
        vec3 p=ro+t*rd;
        //计算交点的法向量
        vec3 norm=calcNormal(p);
        //定义光源
        vec3 light=vec3(cos(u_time),2.,sin(u_time));
        light=vec3(2.0,2.,1.0);

        //计算漫反射
        float diff=dot(normalize(light-p),norm);
        diff=clamp(diff,0.,1.);
        
        //增加环境光
        float ambt=.031;
        //计算高光
        float powRatio=12.;
        vec3 viewDir=normalize(vec3(uv,0.)-p);
        vec3 reflectDir=reflect(-light,norm);
        float spec=pow(max(dot(viewDir,reflectDir),0.),powRatio);
        spec=clamp(spec,0.,1.);
        
        color+=vec3(.4627,.6196,.5569)*diff;
        color+=vec3(.1)*spec;
        color+=vec3(ambt);
    }
    //gamma矫正 这里取0.5次幂
    return sqrt(color);
}

vec3 anti_align(){
    vec3 color=vec3(0.);
    for(int m=0;m<AA;m++){
        for(int n=0;n<AA;n++){
            vec2 offset=2.*(vec2(float(m),float(n))/float(AA)-.5);
            vec2 uv=fixUV(gl_FragCoord.xy+offset);
            color+=render(uv);
        }
    }
    return color;
}

void main(){
    
    vec2 uv=fixUV(gl_FragCoord.xy);
    vec3 color=vec3(0.);
    
    color+=anti_align();
    // color=render(uv);
    
    gl_FragColor=vec4(vec3(color)/float(AA*AA),1.);
    
}